package com.elitel.frame.web.serverreqstat.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.elitel.common.utils.RedisUtils;
import com.elitel.common.utils.StringUtils;
import com.elitel.frame.main.dao.SysReqLogMapper;
import com.elitel.frame.web.cfgserverinfo.dao.CfgServerInfoDao;
import com.elitel.frame.web.cfgserverinfo.entity.CfgServerInfo;
import com.elitel.frame.web.common.idworker.IdWorker;
import com.elitel.frame.web.common.page.PageUtils;
import com.elitel.frame.web.serverreqstat.dao.ServerReqStatDao;
import com.elitel.frame.web.serverreqstat.dto.ServerReqStatDTO;
import com.elitel.frame.web.serverreqstat.entity.ServerAppStat;
import com.elitel.frame.web.serverreqstat.entity.ServerErrorStat;
import com.elitel.frame.web.serverreqstat.entity.ServerReqSimpleStat;
import com.elitel.frame.web.serverreqstat.entity.ServerReqStat;
import com.elitel.frame.web.serverreqstat.service.ServerReqStatService;
import com.elitel.frame.web.sysreqlog.dao.SysReqDetailDao;
import com.elitel.frame.web.sysreqlog.dao.SysReqLogDao;
import com.elitel.frame.web.sysreqlog.entity.SysReqDetail;
import com.elitel.frame.web.sysreqlog.entity.SysReqLog;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @author m
 */
@Slf4j
@Service
public class ServerReqStatServiceImpl implements ServerReqStatService {

    private static final String reqStatRecent = "dscloud:reqstat:recent";
    private static final String SEQ = "&-&";
    private boolean subStrFlag = true;

    @Value("${isUseTenant}")
    private Boolean isUseTenant;
    @Resource
    private SysReqLogMapper sysReqLogMapper;
    @Resource
    private ServerReqStatDao serverReqStatDao;
    @Resource
    private SysReqDetailDao sysReqDetailDao;
    @Resource
    private SysReqLogDao sysReqLogDao;
    @Resource
    private CfgServerInfoDao cfgServerInfoDao;

    private void setBgEdTm(ServerReqStatDTO dto) {
        if (dto.getDays() == null && (dto.getBgtm() == null || dto.getEdtm() == null)) {
            throw new RuntimeException("请选择查询时间");
        }
        if (dto.getBgtm() == null || dto.getEdtm() == null) {
            dto.setBgtm(LocalDateTime.now().minusDays(dto.getDays()));
            dto.setEdtm(LocalDateTime.now());
        } else {
            LocalDateTime bgtm = dto.getBgtm();
            LocalDateTime edtm = dto.getEdtm();
            // 获取两个时间的天数差
            long daysDiff = ChronoUnit.DAYS.between(bgtm, edtm);
            dto.setDays(Integer.valueOf(daysDiff + ""));
        }
    }

    @Override
    public ServerReqSimpleStat getServerReqSimpleStat(ServerReqStatDTO dto) {
        this.setBgEdTm(dto);
        String flag;
        List<String> servCodes;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
            dto.setServCodes(servCodes);
            dto.setFlag(flag);
        }
        ServerReqSimpleStat serverReqSimpleStat = serverReqStatDao.selectServerReqSimpleStat(dto);
        CfgServerInfo cfgServerInfo = new CfgServerInfo();
        cfgServerInfo.setStatus(1);
        int count = cfgServerInfoDao.count(cfgServerInfo);
        serverReqSimpleStat.setServerCount(count);
        ServerReqSimpleStat nameAndMax = serverReqStatDao.selectMaxReqServer(dto);
        if (nameAndMax != null) {
            serverReqSimpleStat.setMaxReqServerCount(nameAndMax.getMaxReqServerCount() == null ? 0 : nameAndMax.getMaxReqServerCount());
            serverReqSimpleStat.setMaxReqServerName(nameAndMax.getMaxReqServerName() == null ? "" : nameAndMax.getMaxReqServerName());
        }
        return serverReqSimpleStat;
    }


    @Override
    public ServerErrorStat getServerErrorStat(ServerReqStatDTO dto) {
        this.setBgEdTm(dto);
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
            dto.setServCodes(servCodes);
            dto.setFlag(flag);
        }
        ServerErrorStat serverErrorStat = serverReqStatDao.selectServerErrorStat(dto);
        ServerErrorStat serverErrorStat2 = serverReqStatDao.selectServerErrorStat2(dto);
        Integer errorReqCount = serverErrorStat2.getErrorReqCount();
        Integer errorReqServerCount = serverErrorStat2.getErrorReqServerCount();
        serverErrorStat.setErrorNoCsCount(errorReqCount);
        serverErrorStat.setErrorNoCsServerCount(errorReqServerCount);
        return serverErrorStat;
    }

    @Override
    public ServerAppStat getServerAppStat(ServerReqStatDTO dto) {
        this.setBgEdTm(dto);
        ServerAppStat res = new ServerAppStat();
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
            dto.setServCodes(servCodes);
            dto.setFlag(flag);
        }
        int appCodeCount = serverReqStatDao.selectAppCodeCount(flag,servCodes);
        res.setAppCount(appCodeCount);

        List<ServerAppStat.AppReqInfo> totalAppReq = serverReqStatDao.selectTotalAppReq(dto);
        res.setTotalList(totalAppReq);

        List<ServerAppStat.AppReqInfo> dayAppReq = serverReqStatDao.selectDayAppReq(dto);
        res.setDayList(dayAppReq);

        return res;
    }

    @Override
    public List<ServerReqStat> getServerStatList(ServerReqStatDTO dto) {
        this.setBgEdTm(dto);
        PageUtils.startPage();
        List<ServerReqStat> serverReqStats = serverReqStatDao.selectServerStatList(dto);
        for (ServerReqStat serverReqStat : serverReqStats) {
            String guid = serverReqStat.getGuid();
            List<String> list = serverReqStatDao.getApps(guid);
            StringBuilder appNames = new StringBuilder();
            for (String name : list) {
                if (name != null) appNames.append(",").append(name);
            }
            if (appNames.length() > 0) {
                serverReqStat.setAppNames(appNames.substring(1));
            }
        }
        return serverReqStats;
    }

    @Override
    public PageInfo<SysReqDetail> pageServerStatListInfo(String startDate, String endDate, Integer days, Integer page,
                                                         Integer rows, String servName,
                                                         Integer respStatus, Integer respTime, Integer isTimeOut) throws ParseException {
        if (page == null) page = 1;
        if (rows == null) rows = 10;
        LocalDateTime startD = null;
        LocalDateTime endD = null;
        if (days != null) {
            endD = LocalDateTime.now();
            startD = endD.minusDays(days);
        } else if (startDate != null || endDate != null) {
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            if (startDate != null) {
                startD = LocalDateTime.parse(startDate, fmt);
            }
            if (endDate != null) {
                endD = LocalDateTime.parse(endDate, fmt);
            }
        }
        PageHelper.startPage(page, rows);
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        List<SysReqDetail> sysReqDetails = sysReqDetailDao.pageSysReqDetail(startD, endD, servName,
                respStatus, respTime, isTimeOut,flag,servCodes);
        PageInfo<SysReqDetail> pageInfo = new PageInfo<>(sysReqDetails);
        return pageInfo;
    }

    @Override
    public int delDetailsByReqDate(LocalDateTime date) {
        return sysReqDetailDao.delDetailsByReqDate(date);
    }

    @Override
    public boolean changeSubStrFlag() {
        return subStrFlag = !subStrFlag;
    }

    @Override
    @Transactional
    public void pullSaveLog() {
        Long size = RedisUtils.zSize(reqStatRecent);
        if (size != null && size > 0) {
            // 分页获取zset中的数据
            int pageSize = 500;
            for (int i = 0; i < size; i += pageSize) {
                Set<String> logSet = RedisUtils.zRange(reqStatRecent, i, i + pageSize);
                if (logSet != null && !logSet.isEmpty()) {
                    ArrayList<SysReqDetail> logList = new ArrayList<>();
                    for (String log : logSet) {
                        if (!log.contains(SEQ)) {
                            logList.add(parseLog(log));
                        } else {
                            logList.add(parseOldLog(log));
                        }
                    }
                    sysReqDetailDao.insertBatch(logList);

                }
            }
            RedisUtils.zRemoveRange(reqStatRecent, 0, size);
        }
    }

    private SysReqDetail parseLog(String log) {
        JSONObject jsonObject = JSONObject.parseObject(log);
        SysReqDetail res = new SysReqDetail();
        res.setId(IdWorker.createStrId());
        res.setAppCode(jsonObject.get("appCode") + "");
        // TODO res.setAppName(jsonObject.get("appName") + "");
        res.setServiceCode(jsonObject.get("serviceCode") + "");
        res.setServiceName(jsonObject.get("serviceName") + "");
        res.setReqTime(new Date(Long.parseLong(jsonObject.get("reqTime") + "")));
        String reqParam = jsonObject.get("reqParam") + "";
        // 截取请求参数
        if (subStrFlag) {
            if (StringUtils.isNotEmpty(reqParam) && reqParam.length() > 1000) {
                String substring = reqParam.substring(0, 1000);
                res.setReqParam(substring);
            }
        } else {
            res.setReqParam(reqParam);
        }

        res.setReqCostTime(Long.parseLong(jsonObject.get("costTime") + ""));
        res.setResStatus(Integer.parseInt(jsonObject.get("status") + ""));
        res.setTimeoutFlag(Integer.parseInt(jsonObject.get("timeoutFlag") + ""));
        res.setErrorInfo(jsonObject.get("errorMsg") == null ? "" : jsonObject.get("errorMsg") + "");
        return res;
    }

    private SysReqDetail parseOldLog(String reqLog) {
        //水库标准化接口&-&1692&-&1748347690526&-&1&-&正常&-&{"apiPath":"/standard/rsvr","bodyStr":""}
        String[] split = reqLog.split(SEQ);

        SysReqDetail res = new SysReqDetail();
        res.setId(IdWorker.createStrId());
        res.setServiceName(split[0]);
        try {
            res.setReqCostTime(Long.parseLong(split[1]));
            res.setReqTime(new Date(Long.parseLong(split[2])));
            res.setResStatus(Integer.parseInt(split[3]));
            res.setErrorInfo(split[4]);
            String json = split[5];
            JSONObject jsonObject = JSONObject.parseObject(json);
            res.setReqParam(jsonObject.get("bodyStr") + "");
        } catch (Exception e) {
            log.error("解析日志失败", e);
        }
        return res;
    }


    @Override
    @Transactional
    public void statSaveLog() {
        // 统计今天的数据
        LocalDateTime now = LocalDateTime.now();
        // 获取今天00:00:00的时间
        LocalDateTime startD = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
        int deleteCount = sysReqLogDao.deleteByReqTime(startD.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        log.info("删除了{}条数据", deleteCount);
        // 获取今天23:59:59的时间
        LocalDateTime endD = now.withHour(23).withMinute(59).withSecond(59);
        String flag=null;
        List<String> servCodes=null;
        if (isUseTenant) {
            flag = "1";
            servCodes=sysReqLogMapper.getByTentId();
        }
        List<SysReqLog> logList = serverReqStatDao.selectStatList(startD, endD,flag,servCodes);
        if (logList != null && !logList.isEmpty()) {
            for (SysReqLog sysReqLog : logList) {
                LocalDateTime reqDate = sysReqLog.getReqDate();
                sysReqLog.setId(IdWorker.createStrId());
                sysReqLog.setReqDate(reqDate);
                sysReqLog.setReqYear(reqDate.getYear());
                sysReqLog.setReqMonth(reqDate.getMonthValue());

            }
            sysReqLogDao.insertBatch(logList);
        }

    }


}
